package com.milepost.workflow.flowdef.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.milepost.workflow.common.dto.BootstrapTableVoDto;
import com.milepost.workflow.common.enums.TaskTypeEnum;
import com.milepost.workflow.flowdef.dto.FlowDefDto;
import com.milepost.workflow.flowdef.entity.FlowDefEntity;
import com.milepost.workflow.flowdef.mapper.FlowDefMapper;
import com.milepost.workflow.flowdef.service.FlowDefService;
import com.milepost.workflow.flowdefform.entity.FlowDefFormEntity;
import com.milepost.workflow.flowdefform.mapper.FlowDefFormMapper;
import com.milepost.workflow.flowdeftask.entity.FlowDefTaskEntity;
import com.milepost.workflow.flowdeftask.mapper.FlowDefTaskMapper;
import com.milepost.workflow.user.service.UserService;
import com.milepost.workflow.util.NamingFormatUtil;
import com.milepost.workflow.util.UUIDUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author huarf
 * @Description
 * @create 2022-03-24 13:49
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class FlowDefServiceImpl extends ServiceImpl<FlowDefMapper, FlowDefEntity> implements FlowDefService {

    private final FlowDefTaskMapper flowDefTaskMapper;

    private final FlowDefFormMapper flowDefFormMapper;

    private final UserService userService;

    @Override
    public boolean createFlowDef(FlowDefDto flowDefDto) {

        //保存流程定义
        insertFlowDef(flowDefDto);

        //保存流程节点
        insertFlowDefTask(flowDefDto);

        return true;
    }

    @Override
    public Page<FlowDefEntity> getFlowDefList(BootstrapTableVoDto bootstrapTableVoDto, FlowDefEntity flowDefEntity) {

        QueryWrapper<FlowDefEntity> flowDefEntityQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNoneBlank(flowDefEntity.getName())) {
            flowDefEntityQueryWrapper.lambda().like(FlowDefEntity::getName, flowDefEntity.getName());
        }

        if (StringUtils.isNoneBlank(flowDefEntity.getDes())) {
            flowDefEntityQueryWrapper.lambda().like(FlowDefEntity::getDes, flowDefEntity.getDes());
        }

        if (flowDefEntity.getOpen() != null) {
            flowDefEntityQueryWrapper.lambda().eq(FlowDefEntity::getOpen, flowDefEntity.getOpen());
        }

        if (bootstrapTableVoDto.sortAvailable()) {
            flowDefEntityQueryWrapper.orderBy(true, bootstrapTableVoDto.isAsc(),
                    NamingFormatUtil.camelhump2LowerCaseUnderline(bootstrapTableVoDto.getSortName()));
        } else {
            //默认排序方式
            flowDefEntityQueryWrapper.orderBy(true, false, "crt_time");
        }

        Page<FlowDefEntity> page = new Page<>(bootstrapTableVoDto.getPageNumber(), bootstrapTableVoDto.getPageSize());
        Page<FlowDefEntity> flowDefEntityPage = baseMapper.selectPage(page, flowDefEntityQueryWrapper);

        return flowDefEntityPage;
    }

    @Override
    public boolean deleteById(String id) {

        //删除流程节点
        flowDefTaskMapper.delete(new QueryWrapper<FlowDefTaskEntity>().lambda().eq(FlowDefTaskEntity::getFlowDefId, id));

        //删除流程表单
        flowDefFormMapper.delete(new QueryWrapper<FlowDefFormEntity>().lambda().eq(FlowDefFormEntity::getFlowDefId, id));

        //删除流程
        int delete = baseMapper.deleteById(id);

        return delete > 0;
    }

    @Override
    public FlowDefDto getFlowDefById(String id) {

        FlowDefDto flowDefDto = new FlowDefDto();

        FlowDefEntity flowDefEntity = baseMapper.selectById(id);

        List<FlowDefTaskEntity> flowDefTaskEntities = flowDefTaskMapper.selectList(new QueryWrapper<FlowDefTaskEntity>().lambda()
                .eq(FlowDefTaskEntity::getFlowDefId, id)
                .orderByAsc(FlowDefTaskEntity::getOrderNum));

        flowDefDto.setFlowDefEntity(flowDefEntity);
        flowDefDto.setFlowDefTaskEntityList(flowDefTaskEntities);

        return flowDefDto;
    }

    @Override
    public boolean modifyFlowDef(FlowDefDto flowDefDto) {
        //更新流程定义
        updateFlowDef(flowDefDto);

        //更新流程节点
        updateFlowDefTask(flowDefDto);

        return true;
    }

    @Override
    public boolean hasPointTask(String id) {

        Long pointTask = flowDefTaskMapper.selectCount(new QueryWrapper<FlowDefTaskEntity>()
                .lambda()
                .eq(FlowDefTaskEntity::getFlowDefId, id)
                .eq(FlowDefTaskEntity::getType, TaskTypeEnum.POINT_TASK.getType()));
        return pointTask > 0;
    }

    @Override
    public boolean hasFlowDefForm(String id) {
        Long flowDefForm = flowDefFormMapper.selectCount(new QueryWrapper<FlowDefFormEntity>()
                .lambda()
                .eq(FlowDefFormEntity::getFlowDefId, id));
        return flowDefForm == 1;
    }

    private void updateFlowDefTask(FlowDefDto flowDefDto) {
        //删除流程节点
        flowDefTaskMapper.delete(new QueryWrapper<FlowDefTaskEntity>().lambda().eq(FlowDefTaskEntity::getFlowDefId, flowDefDto.getFlowDefEntity().getId()));

        //重新添加
        insertFlowDefTask(flowDefDto);
    }

    private void updateFlowDef(FlowDefDto flowDefDto) {
        baseMapper.updateById(flowDefDto.getFlowDefEntity());
    }

    private void insertFlowDefTask(FlowDefDto flowDefDto) {

        List<FlowDefTaskEntity> flowDefTaskEntityList = flowDefDto.getFlowDefTaskEntityList();
        String flowDefId = flowDefDto.getFlowDefEntity().getId();
        for (FlowDefTaskEntity flowDefTaskEntity : flowDefTaskEntityList) {
            flowDefTaskEntity.setId(UUIDUtil.randomUUID());
            flowDefTaskEntity.setFlowDefId(flowDefId);
            flowDefTaskMapper.insert(flowDefTaskEntity);
        }
    }

    private void insertFlowDef(FlowDefDto flowDefDto) {

        FlowDefEntity flowDefEntity = flowDefDto.getFlowDefEntity();
        flowDefEntity.setId(UUIDUtil.randomUUID());
        flowDefEntity.setCrtTime(new Date());
        flowDefEntity.setOpen(1);
        baseMapper.insert(flowDefEntity);
    }

}
